package com.example.attempt.controller;

import com.example.attempt.entity.*;
import com.example.attempt.service.impl.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

@RestController
public class AssessmentController {
    @Autowired
    private AssessmentServiceImpl assessmentImpl;
    @Autowired
    private GradeServiceImpl gradeImpl;
    @Autowired
    private SubmitServiceImpl submitImpl;
    @Autowired
    private TeacherServiceImpl teacherImpl;
    @Autowired
    private StudentServiceImpl studentImpl;
    @Autowired
    private AssistantServiceImpl assistantImpl;
    @Autowired
    private HomeworkServiceImpl homeworkImpl;
    @Autowired
    private StatisticsServiceImpl statisticsImpl;

    //添加互评
    @PostMapping(path = "/addAssessment")
    public int addAsse(@RequestBody Assessment asse){
        if (assessmentImpl.getAsseByHidSid(
                submitImpl.queryBySubId(asse.getSubmitId()).getHid(),
                submitImpl.queryBySubId(asse.getSubmitId()).getSid()) != null){
            return 1; //已有该互评
        }
        if (studentImpl.queryById(asse.getSid1())==null ||
                studentImpl.queryById(asse.getSid2())==null ||
                studentImpl.queryById(asse.getSid3())==null ){
            return 2; //学生不存在
        }
        if (teacherImpl.queryById(asse.getTid())==null){
            return 3; //老师不存在
        }
        if (assistantImpl.queryById(asse.getAid())==null){
            return 4; //助教不存在
        }
        System.out.println("进来添加互评了捏");
        return assessmentImpl.addAsse(asse);
    }

    //删除互评
    @PostMapping(path = "/deleteAssessment")
    public int deleteAsse(@RequestParam(value = "submitId") int submitId){
        if (assessmentImpl.getAsseByHidSid(
                submitImpl.queryBySubId(submitId).getHid(),
                submitImpl.queryBySubId(submitId).getSid()) != null){
            return 1; //互评不存在
        }
        return deleteAsse(submitId);
    }

    //获取互评
    @RequestMapping(path = "/getAssessment")
    public List<Assessment> getAssessment(){
        return assessmentImpl.queryAll();
    }

    @PostMapping(path = "/getAsseByHidSid")
    public Assessment getAsseByHidSid(@RequestParam(value = "hid") int hid,
                                      @RequestParam(value = "sid") String sid){
        if(assessmentImpl.getAsseByHidSid(hid,sid)!=null){
//            System.out.println(submitId);
//            System.out.println(assessmentImpl.getAsseByHidSid(submitId));
            return assessmentImpl.getAsseByHidSid(hid,sid);
        }
        else{
            return new Assessment();
        }
    }

    @PostMapping(path = "/getAsseBySid")
    public List<Evaluation> getAsseBySid(@RequestParam(value = "sid") String sid,
                                      @RequestParam(value = "hid") int hid){
        if(assessmentImpl.getAsseBySid(sid, hid)!=null){
            return assessmentImpl.getAsseBySid(sid, hid);
        }
        else{
            return null;
        }
    }

    @PostMapping(path = "/getAsseByTid")
    public List<Evaluation> getAsseByTid(@RequestParam(value = "tid") String tid,
                                      @RequestParam(value = "hid") int hid){
        if(assessmentImpl.getAsseByTid(tid, hid)!=null){
            return assessmentImpl.getAsseByTid(tid, hid);
        }
        else{
            return null;
        }
    }

    @PostMapping(path = "/getAsseByAid")
    public List<Evaluation> getAsseByAid(@RequestParam(value = "aid") String aid,
                                      @RequestParam(value = "hid") int hid){
        if(assessmentImpl.getAsseByAid(aid, hid)!=null){
            return assessmentImpl.getAsseByAid(aid, hid);
        }
        else{
            return null;
        }
    }

    //判断是否超过截止时间
    @PostMapping(path = "/isAfterDtime")
    public int isAfterOrBeforeDtime(@RequestParam(value = "hid") int hid){
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime nowTime = LocalDateTime.parse(LocalDateTime.now().format(df), df);
        LocalDateTime dtime = homeworkImpl.queryByHid(hid).getDtime();
        if(dtime!=null && nowTime.isAfter(dtime)) //超过截止时间
            return 1;
        else if(dtime!=null && nowTime.isBefore(dtime)) //未到截止时间
            return -1;
        return 0;
    }


    //学生写互评
    @PostMapping(path = "/updateStuAsse")
    public int updateStuComment(@RequestParam(value = "submitId") int submitId,
                                @RequestParam(value = "sid") String sid,
                                @RequestParam(value = "grade") double grade,
                                @RequestParam(value = "comment") String comment){
        //成绩输入错误
        if(grade<=0 || grade>100)
            return 1;

        //超过截止时间
        if(isAfterOrBeforeDtime(submitImpl.queryBySubId(submitId).getHid())==1){
            System.out.println("超过互评截止时间，不能添加互评");
            return 2;
        }

        //更新互评
        if(assessmentImpl.selectBySid1(submitId, sid)!=null){
            assessmentImpl.updateS1comment(submitId, comment);
            gradeImpl.updateGradeS1(submitId, grade);
            return 0;
        }
        else if(assessmentImpl.selectBySid2(submitId, sid)!=null){
            assessmentImpl.updateS2comment(submitId, comment);
            gradeImpl.updateGradeS2(submitId, grade);
            return 0;
        }
        else if(assessmentImpl.selectBySid3(submitId, sid)!=null){
            assessmentImpl.updateS3comment(submitId, comment);
            gradeImpl.updateGradeS3(submitId, grade);
            return 0;
        }
        System.out.println("添加互评评论错误啦");
        return -1;
    }

    //老师写互评
    @PostMapping(path = "/updateTeaAsse")
    public int updateTeaComment(@RequestParam(value = "submitId") int submitId,
                                @RequestParam(value = "grade") double grade,
                                @RequestParam(value = "comment") String comment) {
        //成绩输入错误
        if(grade<=0 || grade>100)
            return 1;

        //已发布成绩
        if(homeworkImpl.queryByHid(submitImpl.queryBySubId(submitId).getHid()).getIsPublish()==1)
            return 2;

        assessmentImpl.updateTcomment(submitId, comment);
        if(grade>0 && grade<=100)
            gradeImpl.updateGradeT(submitId, grade);
        else
            return 1;
        return 0;
    }

    //助教写互评
    @PostMapping(path = "/updateAssAsse")
    public int updateAssComment(@RequestParam(value = "submitId") int submitId,
                                @RequestParam(value = "grade") double grade,
                                @RequestParam(value = "comment") String comment) {
        //容错？
        assessmentImpl.updateAcomment(submitId, comment);
        if(grade>0 && grade<=100)
            gradeImpl.updateGradeA(submitId, grade);
        else
            return 1;
        return 0;
    }

    //是否分配互评
    @PostMapping(path = "/isDistribute")
    public int isDistribute(@RequestParam(value = "hid") int hid){
        //提交作业人数不足
        if(submitImpl.getSubmitNumber(hid)<3)
            return -1;
        //已分配互评
        if(homeworkImpl.queryByHid(hid).getIsDistribute()==1)
            return 1;
        else
            return 0;
    }

    //取消分配互评
    @PostMapping(path = "/cancelDistribute")
    public int cancelDistribute(@RequestParam(value = "hid") int hid){
        System.out.println("----------------------------------取消互评hid"+hid+"---------------------------------");
        //未分配互评
        if(homeworkImpl.queryByHid(hid).getIsDistribute()==0)
            return -1;
        //取消互评
        List<Integer> subId = submitImpl.getSubIdByHid(hid);
        for (Integer i : subId) {
            assessmentImpl.updateAcomment(i, null);
            assessmentImpl.updateTcomment(i, null);
            assessmentImpl.updateS1comment(i, null);
            assessmentImpl.updateS2comment(i, null);
            assessmentImpl.updateS3comment(i, null);
            Assessment assessment = new Assessment();
            assessment.setSubmitId(i);
            assessment.setSid1(null);
            assessment.setSid2(null);
            assessment.setSid3(null);
            assessmentImpl.updateAsse(assessment);

            gradeImpl.updateGrade(hid, submitImpl.queryBySubId(i).getSid(), -1);
            gradeImpl.updateGradeA(i, -1);
            gradeImpl.updateGradeT(i, -1);
            gradeImpl.updateGradeS1(i, -1);
            gradeImpl.updateGradeS2(i, -1);
            gradeImpl.updateGradeS3(i, -1);
        }
        //标记未发布互评
        homeworkImpl.updateIsDistribute(hid,0);
        homeworkImpl.updateDtime(null,hid);

        //取消发布成绩
        cancelPublish(hid);
        return 0;
    }

    //分配互评
    @PostMapping(path = "/distributeAsse")
    public int distributeAsse(@RequestParam(value = "hid") int hid,
                              @RequestParam(value = "dtime") String dtime){
        //已分配互评
        if(homeworkImpl.queryByHid(hid).getIsDistribute()==1)
            return -1;
        //获取所有提交作业号
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime time = LocalDateTime.parse(dtime,df);
        List<Integer> subId = submitImpl.getSubIdByHid(hid);
        System.out.println(subId);
        //获取交作业的学号
        List<String> allStudents = new ArrayList<>(subId.size());
        for(int i = 0; i < subId.size(); i++){
            String sid = submitImpl.queryBySubId(subId.get(i)).getSid();
            if(gradeImpl.getGradesByHidSid(hid,sid).getGrade()==0){//查重分数高
                subId.remove(i);
                i--;
                continue;
            }
            allStudents.add(sid);
        }
        System.out.println(allStudents);
        System.out.println("_____________________" + subId.size());
        System.out.println("_____________________" + subId);
        //分配互评
        List<String>[] results = distributeHomework(allStudents);
        //添加互评
        for (int i = 0; i < subId.size(); i++) {
//            System.out.println("作业 " + subId.get(i) + " 的评分情况:");
//            for (String review : results[i]) {
//                System.out.println("  学生 " + review);
//            }
//            if(gradeImpl.getGradesByHidSid(hid,submitImpl.queryBySubId(subId.get(i)).getSid()).getGrade()==0)//查重分数高
//                continue;
            //获取该作业的评分占比
            int hId = submitImpl.queryBySubId(subId.get(i)).getHid();
            float stuRate = homeworkImpl.queryByHid(hId).getStudentRate();
//            float teaRate = homeworkImpl.queryByHid(hId).getTeacherRate();
            float assRate = homeworkImpl.queryByHid(hId).getAssistanceRate();
            Assessment assessment = new Assessment();
            assessment.setSubmitId(subId.get(i));
            //若为0，则不给该作业分配助教/学生/老师
            if(stuRate!=0){
                assessment.setSid1(results[i].get(0));
                assessment.setSid2(results[i].get(1));
                assessment.setSid3(results[i].get(2));
            }
            //老师不能为0
//            if(teaRate!=0)
//                assessment.setTid(homeworkImpl.queryByHid(hid).getTid());
            if(assRate!=0)
                assessment.setAid(assistantImpl.queryByTid(homeworkImpl.queryByHid(hid).getTid()).getAid());
            assessmentImpl.updateAsse(assessment);
        }
        //标记已发布互评
        homeworkImpl.updateIsDistribute(hid,1);
        homeworkImpl.updateDtime(time,hid);
        return 0;
    }

    public List<String>[] distributeHomework(List<String> allStudents) {
        int numStudents = allStudents.size();
        int numReviewers = 3; //评阅人数量
        List<Integer> students = new ArrayList<>();

        // 初始化学生顺序
        for (int i = 0; i < numStudents; i++) {
            students.add(i);
        }

        // 随机打乱学生顺序
        long seed = System.nanoTime();
        Collections.shuffle(students, new Random(seed));

        // 检查学生排序是否符合要求
        for (int i = 0; i < numStudents; i++) {
            int student = i;
            int adjacentStudent1 = students.get((i + 1) % numStudents);
            int adjacentStudent2 = students.get((i + 2) % numStudents);

            // 重新打乱学生顺序：学生1不能在123的位置上
            if (student == students.get(i) || student == adjacentStudent1 || student == adjacentStudent2) {
                Collections.shuffle(students, new Random(System.nanoTime()));
                i = -1; // 重新检查学生排序
            }
        }

        // 存储每份作业的评分人
        ArrayList[] assignmentFeedback = new ArrayList[numStudents]; //n个作业
        for (int i = 0; i < numStudents; i++) {
            assignmentFeedback[i] = new ArrayList<>();
            for (int j = 0; j < numReviewers; j++) {
                assignmentFeedback[i].add(allStudents.get(students.get((i + j) % numStudents)));
            }
        }
        return assignmentFeedback;
    }

    //是否能发布成绩
    @PostMapping(path = "/isPublishGrade")
    public int isPublishGrade(@RequestParam(value = "hid") int hid) {
        System.out.println("------------------------进来判断能不能发布成绩了-----------------------");
        //作业不存在
        if(homeworkImpl.queryByHid(hid)==null){
            System.out.println("作业不存在");
            return -2;
        }
        //未到截止时间
        if(isAfterOrBeforeDtime(hid)==-1){
            System.out.println("未到截止时间");
            return -1;
        }
        //已发布
        if(homeworkImpl.queryByHid(hid).getIsPublish()==1){
            System.out.println("已发布");
            return 1;
        }
        System.out.println("可以发布");
        return 0;
    }

    //发布成绩
    @PostMapping(path = "/publishGrade")
    public int publishGrade(@RequestParam(value = "hid") int hid) {
        //未到截止时间
        if(isAfterOrBeforeDtime(hid)==-1)
            return -4;

        //已发布
        if(homeworkImpl.queryByHid(hid).getIsPublish()==1)
            return -1;

        //获取所有提交作业号
        List<Integer> subId = submitImpl.getSubIdByHid(hid);

        //计算成绩
        for (Integer integer : subId) {
            String sid = submitImpl.queryBySubId(integer).getSid();
            if (gradeImpl.getGradesByHidSid(hid, sid).getGrade() == 0)//查重分数高
                continue;
            double grade = calculateGradeByHidSid(hid, sid);
            if (grade == -2) //助教没评
                return -2;
            if (grade == -3) //老师没评
                return -3;
            gradeImpl.updateGrade(hid, sid, grade);
        }

        //标记已发布成绩
        homeworkImpl.updateIsPublish(hid,1);
        //添加统计
        Statistics sta = new Statistics();
        sta.setHid(hid);
        statisticsImpl.addStatistics(sta);
        return 0;
    }

    //取消发布成绩
    @PostMapping(path = "/cancelPublish")
    public int cancelPublish(@RequestParam(value = "hid") int hid){
        System.out.println("----------------------------------取消成绩hid"+hid+"---------------------------------");
        //未发布成绩
        if(homeworkImpl.queryByHid(hid).getIsPublish()==0)
            return -1;

        //取消成绩
        List<Integer> subId = submitImpl.getSubIdByHid(hid);
        for (Integer integer : subId) {
            String sid = submitImpl.queryBySubId(integer).getSid();
            gradeImpl.updateGrade(hid, sid, -1);
        }
        homeworkImpl.updateIsPublish(hid,0);

        return 0;
    }

    //计算某学生某作业成绩
    @PostMapping(path = "/calculateGradeByHidSid")
    public double calculateGradeByHidSid(@RequestParam(value="hid") int hid,
                                         @RequestParam(value="sid") String sid){
        int flag = 0;
        double gradeA = gradeImpl.getGradesByHidSid(hid,sid).getGradeA();
        double gradeT = gradeImpl.getGradesByHidSid(hid,sid).getGradeT();
        double gradeS1 = gradeImpl.getGradesByHidSid(hid,sid).getGradeS1();
        double gradeS2 = gradeImpl.getGradesByHidSid(hid,sid).getGradeS2();
        double gradeS3 = gradeImpl.getGradesByHidSid(hid,sid).getGradeS3();
        float stuRate = homeworkImpl.queryByHid(hid).getStudentRate();
        float teaRate = homeworkImpl.queryByHid(hid).getTeacherRate();
        float assRate = homeworkImpl.queryByHid(hid).getAssistanceRate();

        //助教需要评但是没有评价
        if(gradeA==-1 && assRate!=0){
            System.out.println("助教没评");
            return -2;
        }

        //老师需要评但是没有评价
        if(gradeT==-1 && teaRate!=0){
            System.out.println("老师没评");
            return -3;
        }

        //获取没有评价的学生数量
        if(gradeS1==-1){
            flag++;
            gradeS1=0;
        }
        if(gradeS2==-1){
            flag++;
            gradeS2=0;
        }
        if(gradeS3==-1){
            flag++;
            gradeS3=0;
        }
        //三个学生都没有在截止时间内评价，把学生成绩按教师成绩计算
        if(flag==3){
            flag--;
            gradeS1 = gradeT;
        }
        double grade = gradeA * assRate + gradeT * teaRate + (gradeS1 + gradeS2 + gradeS3) * stuRate / (3-flag);
        BigDecimal two = new BigDecimal(grade);
        grade = two.setScale(2, RoundingMode.HALF_UP).doubleValue(); //保留1位小数

        return grade;
    }

    //获取某作业成绩
    @PostMapping(path = "/getGradesByHidSid")
    public Grade getGradesByHidSid(@RequestParam(value = "hid") int hid,
                                   @RequestParam(value = "sid") String sid){
        if(gradeImpl.getGradesByHidSid(hid, sid)==null)
            return null;
        //数据库中有成绩
        return gradeImpl.getGradesByHidSid(hid, sid);
    }

    //学生申诉
    @PostMapping(path = "/stuAppeal")
    public int stuAppeal(@RequestParam(value = "hid") int hid,
                         @RequestParam(value = "sid") String sid,
                         @RequestParam(value = "reason") String reason){
//        System.out.println(sid+" "+reason);
        if(gradeImpl.getGradesByHidSid(hid, sid)==null) { //不存在
            System.out.println("要修改的成绩不存在");
            return -1;
        }

        //申诉原因为空
        if(reason.isEmpty())
            return -2;

        gradeImpl.updateAppeal(hid, sid,1, reason);
        return 0;
    }

    //是否能申诉
    @PostMapping(path = "/canAppeal")
    public int canAppeal(@RequestParam(value = "hid") int hid,
                        @RequestParam(value = "sid") String sid){
        if(gradeImpl.getGradesByHidSid(hid, sid)==null) //不存在
            return -2;

        if(gradeImpl.getGradesByHidSid(hid, sid).getGrade() == 0) //高相似度允许申诉
            return 0;

        //相差十分不能申诉
        int flag = 0;
        double gradeT = gradeImpl.getGradesByHidSid(hid,sid).getGradeT();
        double gradeS1 = gradeImpl.getGradesByHidSid(hid,sid).getGradeS1();
        double gradeS2 = gradeImpl.getGradesByHidSid(hid,sid).getGradeS2();
        double gradeS3 = gradeImpl.getGradesByHidSid(hid,sid).getGradeS3();

        //获取没有评价的学生数量
        if(gradeS1==-1){
            flag++;
            gradeS1=0;
        }
        if(gradeS2==-1){
            flag++;
            gradeS2=0;
        }
        if(gradeS3==-1){
            flag++;
            gradeS3=0;
        }

        //三个学生都没有在截止时间内评价，把学生成绩按教师成绩计算
        if(flag==3){
            flag--;
            gradeS1 = gradeT;
        }

        double grade = (gradeS1 + gradeS2 + gradeS3) / (3-flag) - gradeT;

        if(grade > 10 || grade < -10)
            return -1;
        return 0;
    }

    //获取申诉理由
    @PostMapping(path = "/getReason")
    public String getReason(@RequestParam(value = "hid") int hid,
                         @RequestParam(value = "sid") String sid){
        if(gradeImpl.getGradesByHidSid(hid, sid)==null)
            return null;
        return gradeImpl.getGradesByHidSid(hid, sid).getReason();
    }

    //学生获取申诉信息
    @PostMapping(path = "/getAppealBySid")
    public List<AppealStu> getAppealBySid(@RequestParam(value = "sid") String sid){
        if(submitImpl.queryBySid(sid)==null)
            return null;
        return gradeImpl.getStuAppeal(sid);
    }

    //老师获取申诉信息
    @PostMapping(path = "/getAppeal")
    public List<Appeal> getAppeal(@RequestParam(value = "cid") String cid){
        return gradeImpl.getAppeal(cid);
    }

    //撤销申诉
    @PostMapping(path = "/cancelAppeal")
    public int cancelAppeal(@RequestParam(value = "hid") int hid,
                            @RequestParam(value = "sid") String sid){
        if(gradeImpl.getGradesByHidSid(hid, sid).getIsAppeal()==0) //未申诉
            return -1;
        if(gradeImpl.getGradesByHidSid(hid, sid)==null) //不存在
            return -2;
        gradeImpl.updateAppeal(hid, sid,0, null);
        return 0;
    }

    //驳回申诉
    @PostMapping(path = "/refuseAppeal")
    public int refuseAppeal(@RequestParam(value = "submitId") int submitId,
                            @RequestParam(value = "refuseReason") String refuseReason){
        if(submitImpl.queryBySubId(submitId)==null)
            return -1;
        gradeImpl.refuseAppeal(submitId,3, refuseReason);
        return 0;
    }

    //获取驳回理由
    @PostMapping(path = "/getRefuseReason")
    public String getRefuseReason(@RequestParam(value = "hid") int hid,
                                  @RequestParam(value = "sid") String sid){
        if(gradeImpl.getGradesByHidSid(hid, sid)==null)
            return null;
        return gradeImpl.getGradesByHidSid(hid, sid).getRefuseReason();
    }

    //老师修改成绩
    @PostMapping(path = "/modifyGrade")
    public int modifyGrade(@RequestParam(value = "submitId") int submitId,
                           @RequestParam(value = "grade") double grade){
        //成绩输入错误
        if(grade>100 || grade<-1)
            return -1;

        //不存在该成绩
        if(submitImpl.queryBySubId(submitId)==null)
            return -2;

        //修改分数
        int hid = submitImpl.queryBySubId(submitId).getHid();
        String Sid = submitImpl.queryBySubId(submitId).getSid();//交作业人的学号
        gradeImpl.modifyGrade(hid, Sid, grade);

        //标记申诉已完成
        String appealReason = gradeImpl.getGradesByHidSid(hid, Sid).getReason();
        gradeImpl.updateAppeal(hid, Sid,2, appealReason);
        return 0;
    }

}